// Description: Single-Page UI for network visualizer.
// Author: keroserene@google.com  (Serene Han)

define(['domReady', 'jquery'], function (domReady, $) {
  var ENTRY_ID_PREFIX = 'v-';
  var BUTTERBAR_TIMEOUT = 1800;
  var gGraphs = {};  // Dict of ID -> Name
  var gSpreadsheets = {};  // Dict of ID -> Spreadsheet Key
  var gEditMode = false;
  var gCurrentGraphID = 0;

  // Hook |entry| (DOM element) to open up a single visualization view.
  function hookGraphEntry(entry, id) {
    var id = entry.id.split('-')[1];
    var name = entry.innerHTML;
    gGraphs[id] = name.trim();
    entry.onclick = function() {
      viewGraph(id);
      $(this).addClass('selected');
    };
  }

  // Display one particular visualization via AJAX.
  function viewGraph(id) {
    window.history.pushState({}, 'unused', '/view/' + id);
    clearView();
    // TODO(keroserene): Add loading spinners maybe.
    $('#view').load('/graph/' + id + ' #ajax-view');
    $('#view').removeClass('hidden');
    $('#view').show()
    $('#btnbar').show();
    $('#btnbar').removeClass('hidden');
    gCurrentGraphID = id;
  }

  // When a visualization is created, prepare a new element in the Entries list
  // to indicate a new entry is being created, while awaiting for the actual
  // visualization to be readied.
  function awaitUpdate() {
    $('#graph-list').prepend(
        '<div id="pending" class="graph-entry">...</div>');
    setTimeout(refreshEntries, 500);
  }

  // Fetch JSON data about all existing visualization entries, and update the
  // DOM list if a new one is found.
  function refreshEntries() {
    var pending = $('#pending');
    console.log('fuck');
    $.getJSON('/data.json', function(data) {
      $.each(data, function(i, entry) {
        if (!pending) {
          return;
        }
        var id = entry[0];
        var name = entry[1];
        var spreadsheet = entry[2];
        gSpreadsheets[id] = spreadsheet;
        if (!(id in gGraphs)) {
          gGraphs[id] = name;
          var entryDOM = pending[0];
          pending = null;
          entryDOM.id = ENTRY_ID_PREFIX + id;
          entryDOM.innerHTML = name;
          hookGraphEntry(entryDOM);
        }
      });
      if (pending) {  // Try again if no new entry was found.
        setTimeout(refreshEntries, 500);
      }
    });
  }

  function hideButtonBar() {
    $('#btnbar').addClass('hidden');
    setTimeout(function () { $('#btnbar').hide(); }, 300);
  }

  // Handler for clicking on "CREATE VISUALIZATION".
  function prepareCreateForm() {
    gEditMode = false;
    clearView();
    $('#btn-save').text('Create');
    $('#btn-delete').hide();
    $('.graph-entry').filter('.selected').removeClass('selected');
    hideButtonBar();
    // Clear the form.
    $('#id_name').val('');
    $('#id_spreadsheet_link').val('')
    shiftSidebar();
  }

  // Handler for clicking on "EDIT".
  function prepareEditForm() {
    gEditMode = true;
    $('#btn-edit').addClass('disabled');
    $('#btn-save').text('Save');
    $('#btn-delete').show();
    $('#id_name').val(gGraphs[gCurrentGraphID]);
    $('#id_spreadsheet_link').val(
        'https://docs.google.com/a/google.com/spreadsheet/ccc?key=' +
        gSpreadsheets[gCurrentGraphID]);
    $('#id_graph_id').val(gCurrentGraphID);  // For delete requests.
    shiftSidebar();
  }

  function saveOrCreate() {
    // TODO(keroserene): Validate spreadsheet format?
    if (!validEntry('id_name', 'Please name your visualization.') ||
        !validEntry('id_spreadsheet_link',
                      'Please provide a valid spreadsheet link.')) {
      return;
    }
    if (gEditMode) {
      updateGraph();
    } else {  // CREATE_MODE
      createGraph();
      awaitUpdate();
    }
    resetSidebar();
  }

  // Validates a form text entry. Returns true if valid, false otherwise.
  function validEntry(entry_id, error_msg) {
    var entry = $('#' + entry_id);
    if (!entry.val()) {
      butterBar(error_msg);
      entry.focus();
      return false;
    }
    return true;
  }

  // Send AJAX POST to create new graph, update local DOM to indicate
  // loading and new graph.
  function createGraph() {
    var data = $('#graph-form').serialize();
    // The trailing slash is /graph/create/ is important.
    $.post('/graph/create/', data, function() {
      console.log('create request complete.');
    });
  }

  function updateGraph() {
    var data = $('#graph-form').serialize();
    // Trailing slash isvital.
    $.post('/graph/' + gCurrentGraphID + '/update/', data, function() {
      console.log('update request complete.');
    });
    var newName = $('#id_name').val();
    gGraphs[gCurrentGraphID] = newName;
    // Rename without bothering with JSON.
    $('#' + ENTRY_ID_PREFIX + gCurrentGraphID).text(newName);
  }

  function deleteGraph() {
    var data = $('#graph-form').serialize()
    $.post('/graph/' + gCurrentGraphID + '/delete/', data, function() {
      console.log('delete request complete.');
    });
    $('#' + ENTRY_ID_PREFIX + gCurrentGraphID).remove();
    clearView();
    hideButtonBar();
    gCurrentGraphID = null;
    window.history.pushState({}, 'unused', '/');
    resetSidebar();
  }

  function shiftSidebar() {
    $('#sidebar').addClass('widened');
    $('#sidebar-content').addClass('shifted');
    $('#edit-pane').show();
  }
  function resetSidebar() {
    $('#sidebar').removeClass('widened');
    $('#sidebar-content').removeClass('shifted');
    $('#edit-pane').hide();
    $('#btn-edit').removeClass('disabled');
  }

  // Clears everything from the viewport. Used prior to loading any new view, or
  // when opening the create visualization pane.
  function clearView() {
    $('.graph-entry').filter('.selected').removeClass('selected');
    $('#view').empty();
    $('#view').hide();
    if ($('#btn-embed').hasClass('active')) {
      toggleEmbedLink();
    }
  }

  // Toggles the embed link. Auto-updates and selects code if needed.
  function toggleEmbedLink() {
    $('#btn-embed').toggleClass('active');
    var embedCode = '<iframe src="' + HOSTNAME + '/graph/' +
                    gCurrentGraphID + '/embed/" ' +
                    'width="1000" height="600"></iframe>';
    var snippet = $('#snippet');
    snippet.text(embedCode);
    snippet.toggleClass('hidden');
    if (!snippet.hasClass('hidden')) {
      snippet.select();
    }
  }

  function butterBar(msg) {
    if (!msg) return;
    var bar = $('#butterbar');
    console.log(msg);
    bar.html(msg);
    bar.removeClass('hidden');
    setTimeout(function() {
      bar.addClass('hidden');
    }, BUTTERBAR_TIMEOUT);
  }

  // Install all AJAX and DOM handlers.
  domReady(function () {
    // Obtain initial data.
    $.getJSON('/data.json', function(data) {
      $.each(data, function(i, entry) {
        var id = entry[0];
        var name = entry[1];
        var spreadsheet = entry[2];
        gGraphs[id] = name;
        gSpreadsheets[id] = spreadsheet;
      });
    });

    // View handlers.
    $.each($('.graph-entry'), function(i, entry) {
      hookGraphEntry(entry);
    });
    if (GRAPH_ID) {  // If initially loaded from django template.
      gCurrentGraphID = GRAPH_ID;
    }

    // Primary button handlers.
    $('#btn-create').click(prepareCreateForm);
    $('.btn-cancel').click(resetSidebar);
    $('#btn-save').click(saveOrCreate);
    $('#btn-edit').click(prepareEditForm);
    $('#btn-delete').click(deleteGraph);
    $('#btn-embed').click(toggleEmbedLink);
  });
});
